package sun.sequence.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import sun.sequence.mapper.SequenceMapper;
import sun.sequence.model.Sequence;
import sun.sequence.service.SequenceService;

import java.util.Date;
import java.util.Objects;

@Slf4j
@Service
@Transactional
public class SequenceServiceImpl implements SequenceService {

    @Autowired
    private SequenceMapper sequenceMapper;

    @Override
    public void insertSelective(Sequence sequence) {
        log.info("sequenceNum:{}", JSON.toJSONString(sequence));
        Assert.isTrue(StringUtils.isNotBlank(sequence.getNamespace()), "namespace 不允许为空");
        Assert.isTrue(StringUtils.isNotBlank(sequence.getBizTag()), "bizTag 不允许为空");
        Objects.requireNonNull(sequence.getMaxId(), "max_id 不允许为空");
        Objects.requireNonNull(sequence.getStep(), "step 不允许为空");
        sequence.setCreateTime(new Date());
        try {
            sequenceMapper.insert(sequence);
        } catch (DuplicateKeyException ex) {
            log.warn("sequenceNum已创建:{}", JSON.toJSONString(sequence));
        }
    }

    @Override
    public Sequence generateNewSequence(String namespace, String bizTag, Long minId) {

        log.info("namespace:{}, bizTag:{}", namespace, bizTag);
        Sequence sequence = selectByNamespaceAndBizTag(namespace, bizTag);
        log.info("sequenceNum:{}", JSON.toJSONString(sequence));
        Objects.requireNonNull(sequence, "sequenceNum查询失败");
        sequence = sequenceMapper.selectByPrimaryKeyAndLock(sequence.getId());
        Sequence updateParams = new Sequence();
        updateParams.setId(sequence.getId());
        long newMaxId = sequence.getMaxId() + sequence.getStep();
        if(minId != null && newMaxId < minId){
            newMaxId = minId;
        }
        updateParams.setMaxId(newMaxId);
        sequenceMapper.updateById(updateParams);
        return sequence;
    }


    @Override
    public Sequence selectByNamespaceAndBizTag(String namespace, String bizTag) {
        log.info("namespace:{}, bizTag:{}", namespace, bizTag);
        Assert.isTrue(StringUtils.isNotBlank(namespace), "namespace 不允许为空");
        Assert.isTrue(StringUtils.isNotBlank(bizTag), "bizTag 不允许为空");

        Sequence params = new Sequence();
        params.setNamespace(namespace);
        params.setBizTag(bizTag);

        return sequenceMapper.selectOne(new QueryWrapper<>(params));
    }

    @Override
    public void initSequence(String namespace, String bizTag, Long initVal, Integer step, String description) {
        Sequence sequence = new Sequence();
        sequence.setNamespace(namespace);
        sequence.setBizTag(bizTag);
        sequence.setMaxId(initVal);
        sequence.setStep(step);
        sequence.setCreateTime(new Date());
        sequence.setDescription(description);

        insertSelective(sequence);
    }
}
